package com.hanklee.demo

import android.Manifest
import android.annotation.SuppressLint
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableLongStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.lifecycle.lifecycleScope
import com.hanklee.demo.ui.theme.DemoTheme
import com.hanklee.demo.utils.AudioRecorder
import com.hanklee.demo.utils.DraftWithOrigin
import com.hanklee.demo.utils.EncryptUtil
import com.hanklee.demo.utils.RTASRConfigs.APPID
import com.hanklee.demo.utils.RTASRConfigs.BASE_URL
import com.hanklee.demo.utils.RTASRConfigs.ORIGIN
import com.hanklee.demo.utils.RTASRConfigs.APIKey
import com.hanklee.demo.utils.RTSTWebSocketListener
import org.java_websocket.WebSocket
import org.java_websocket.client.WebSocketClient
import org.java_websocket.handshake.ServerHandshake
import java.lang.Thread.sleep
import java.net.URI
import java.net.URLEncoder
import java.nio.ByteBuffer
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
import java.util.concurrent.CountDownLatch


class MainActivity : ComponentActivity() {

    private val TAG = MainActivity::class.java.simpleName

    // 生成握手参数
    fun getHandShakeParams(appId: String, secretKey: String?): String {
        val ts = (System.currentTimeMillis() / 1000).toString() + ""
        try {
            val signal = EncryptUtil.HmacSHA1Encrypt(EncryptUtil.MD5(appId + ts), secretKey)
            return "?appid=" + appId + "&ts=" + ts + "&signa=" + URLEncoder.encode(
                signal,
                "UTF-8"
            ) + "&pd=" + "gov" + "&roleType=" + "2"
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
        }
        return ""
    }

    val transcriptionResults = mutableStateOf("")
    val isRecording = mutableStateOf(false)
    val url = URI(BASE_URL + getHandShakeParams(APPID, APIKey))
    val draft = DraftWithOrigin(ORIGIN)
    val handshakeSuccess = CountDownLatch(1)
    val connectClose = CountDownLatch(1)
    val audioRecorder by lazy {
        AudioRecorder(lifecycleScope = lifecycleScope)
    }

    private val lastResultTime by lazy { mutableLongStateOf(0L) }

    fun getWebSocketClient(): RTSTWebSocketClient {
        return RTSTWebSocketClient(url, draft, object :
            RTSTWebSocketListener {
            override fun onOpen(handshake: ServerHandshake) {
                println("\t连接建立成功！")
            }

            override fun onMessage(action: String, message: String) {
                when (action) {
                    "started" -> {
                        println("\t握手成功！sid: $message")
                        handshakeSuccess.countDown()
                    }

                    "result" -> {
                        Log.d(TAG, "onMessage: $message")
                        lastResultTime.longValue = System.currentTimeMillis()
                        val currentTime =
                            SimpleDateFormat(
                                "yyyy-MM-dd HH:mm:ss",
                                Locale.getDefault()
                            ).format(Date())

                        if (message.isEmpty()) {
                            return
                        }

                        val curT = System.currentTimeMillis()
                        Log.d(TAG, "onMessage C: $curT")
                        Log.d(TAG, "onMessage L: ${lastResultTime.longValue}")
                        Log.d(TAG, "onMessage B: ${curT - lastResultTime.longValue < 5}")
                        if (curT - lastResultTime.longValue < 5) {
                            if (transcriptionResults.value.isEmpty()) {
                                transcriptionResults.value += "\n $currentTime:"
                            }
                            transcriptionResults.value += message
                        } else {
                            transcriptionResults.value += "\t $currentTime: $message\n"
                        }
                    }

                    "error" -> {
                        println("\tError: $message")
                    }
                }
            }

            override fun onError(exception: Exception) {
                println("\t连接发生错误：" + exception.message + ", " + Date())
                exception.printStackTrace()
            }

            override fun onClose(code: Int, reason: String, remote: Boolean) {
                connectClose.countDown()
                println("\t连接关闭：" + reason + ", " + Date())
            }

            override fun onMessageBytes(bytes: ByteBuffer) {
                println("\t收到字节消息：" + String(bytes.array(), charset("UTF-8")))
            }
        })
    }

    fun send(client: WebSocketClient, bytes: ByteArray?) {
        if (client.isClosed) {
            throw RuntimeException("client connect closed!")
        }
        client.send(bytes)
    }

    lateinit var client: RTSTWebSocketClient

    val permissionState =
        mutableStateOf(Manifest.permission.RECORD_AUDIO)

    @SuppressLint("MissingPermission")
    val launcher =
        registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
            if (isGranted) {
                client = getWebSocketClient()
                client.connect()
                while (!client.readyState.equals(WebSocket.READYSTATE.OPEN)) {
                    println("\t连接中")
                    sleep(1000)
                }
                // 等待握手成功
                handshakeSuccess.await()
                //权限获取到之后的动作
                audioRecorder.startRecording(recorderListener = { data, bytesRead, byteSize ->
                    send(client, data)
                    // 建议音频流每40ms发送1280字节的数据
                    sleep(40)
                })
            } else {
                Toast.makeText(
                    this@MainActivity,
                    "没有录音权限，无法使用录音功能",
                    Toast.LENGTH_SHORT
                ).show()
                isRecording.value = false
            }
        }

    @SuppressLint("StateFlowValueCalledInComposition")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            DemoTheme {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    RealTimeSpeechTranscriptionComponent(
                        isRecording = isRecording.value,
                        results = transcriptionResults.value,
                        onClear = {
                            transcriptionResults.value = ""
                        },
                        onClick = {
                            if (!isRecording.value) {
                                launcher.launch(permissionState.value)
                            } else {
                                // 发送结束标识
                                send(client, "{\"end\": true}".toByteArray())
                                // 等待连接关闭
                                connectClose.await()
                                audioRecorder.stopRecording()
                            }
                            isRecording.value = !isRecording.value
                        }
                    )
                }
            }
        }
    }
}

@Preview
@Composable
fun PreviewRealTimeSpeechTranscriptionComponent() {
    RealTimeSpeechTranscriptionComponent(
        isRecording = false,
        results = "Hello, World!",
        onClick = {},
        onClear = {}
    )
}

@Composable
fun RealTimeSpeechTranscriptionComponent(
    isRecording: Boolean,
    results: String,
    onClick: () -> Unit,
    onClear: () -> Unit
) {
    Column(
        modifier = Modifier.fillMaxSize()
    ) {
        val scrollState = rememberScrollState()
        LaunchedEffect(key1 = results) {
            scrollState.animateScrollTo(scrollState.maxValue)
        }
        Text(
            text = results,
            modifier = Modifier
                .verticalScroll(state = scrollState)
                .weight(1f)
        )
        Row {
            Button(
                onClick = onClick,
                modifier = Modifier
                    .fillMaxWidth()
                    .weight(1f)
                    .padding(horizontal = 8.dp, vertical = 8.dp)
                    .height(60.dp)
            ) {
                Text(
                    if (isRecording) {
                        "停止"
                    } else {
                        "开始"
                    }
                )
            }

            Button(
                onClick = onClear,
                modifier = Modifier
                    .fillMaxWidth()
                    .weight(1f)
                    .padding(horizontal = 8.dp, vertical = 8.dp)
                    .height(60.dp)
            ) {
                Text("清空")
            }
        }
    }
}